from common.libs.food.FoodService import ChangeFoodStockLog
from common.libs.queue.QueueService import QueueService
from common.libs.pay.GenerateOrderSn import IdWorker
from common.models.pay import PayOrderCallbackData
from common.models.pay import PayOrderItem
from common.models.member import MemberAddress
from common.models.food import FoodSaleChangeLog
from common.libs.Helper import getCurrentDate
from common.models.pay import PayOrder
from common.models.food import Food
from application import db
from decimal import Decimal

class PayService(object):

    @staticmethod
    def generateOrderSn():
        """
        雪花算法生成19位订单id
        :return:
        """
        worker = IdWorker()
        return str(worker.get_id())

    def CreateOrder(self, member_id, yun_price,default_address, note, items):
        result = {'code': 200, 'msg': '操作成功', 'data': {}}
        current_item = 0
        pay_price = Decimal('0.00')
        foods_ids = []
        for item in items:
            if Decimal(item['price']) < 0:
                current_item += 1
                continue
            pay_price = pay_price + Decimal(item['price']) * Decimal(item['number'])
            foods_ids.append(item['id'])
        if current_item >= len(items):
            result['code'] = -1
            result['msg'] = '价格异常，请重试！'
            return result
        total_price = pay_price + yun_price

        try:
            # 使用悲观锁进行并发控制
            temp_food_list = db.session.query(Food).filter(Food.id.in_(foods_ids)) \
                .with_for_update().all()

            temp_stock_mapping = {}
            for temp_food in temp_food_list:
                temp_stock_mapping[temp_food.id] = temp_food.stock
            # 默认地址的id
            address = MemberAddress.query.filter_by(is_default = 1).first()

            # 生成订单表
            model_pay = PayOrder()
            model_pay.order_sn = self.generateOrderSn()
            model_pay.member_id = member_id
            model_pay.total_price = total_price
            model_pay.yun_price = yun_price
            model_pay.pay_price = pay_price
            model_pay.note = note
            model_pay.status = -8
            model_pay.express_status = -8
            model_pay.express_address_id = address.id
            model_pay.express_info = default_address
            model_pay.updated_time = getCurrentDate()
            model_pay.created_time = getCurrentDate()
            db.session.add(model_pay)

            for item in items:
                food_stock = temp_stock_mapping[item['id']]

                if Decimal(item['price']) < 0:
                    continue

                if item['number'] > food_stock:
                    raise Exception(
                        '库存不足！当前库存为：{}，你购买的数量为：{}' \
                            .format(food_stock, item['number'])
                    )

                # 更改库存
                temp_ret = Food.query.filter(Food.id == item['id']).update({
                    "stock": food_stock - item['number']
                })

                if not temp_ret:
                    raise Exception('下单失败,请重新下单！')

                # 生成订单详情表
                model_item = PayOrderItem()
                model_item.pay_order_id = model_pay.id
                model_item.member_id = member_id
                model_item.quantity = item['number']
                model_item.price = float(item['price'])*item['number']
                model_item.food_id = item['id']
                model_item.note = note
                model_item.updated_time = getCurrentDate()
                model_item.created_time = getCurrentDate()
                db.session.add(model_item)

                # 添加库存变更记录
                ChangeFoodStockLog(item['id'], -item['number'], '顾客购买')

            # 提交到数据库
            db.session.commit()
            # 返回数据
            result['data'] = {
                'id': model_pay.id,
                'order_id': model_pay.order_sn,
                'total_price': str(total_price)
            }
        except Exception as error:
            db.session.rollback()
            result['code'] = -1
            result['msg'] = str(error)
            return result

        return result

    def orderSuccess(self, pay_order_id=0, params=None):

        # 修改订单表的状态，并增加第三方流水号
        pay_order_info = PayOrder.query.filter_by(id=pay_order_id).first()
        if not pay_order_info:
            return False
        pay_order_info.pay_sn = params['pay_sn']
        pay_order_info.status = 1
        pay_order_info.express_status = -7
        pay_order_info.pay_time = getCurrentDate() # 更新支付时间
        pay_order_info.updated_time = getCurrentDate()
        pay_order_info.update()

        # 增加美食销售日志
        pay_order_item_list = PayOrderItem.query.filter_by(pay_order_id=pay_order_id).all()
        model_sale = FoodSaleChangeLog()
        for item in pay_order_item_list:
            model_sale.food_id = item.food_id
            model_sale.quantity = item.quantity
            model_sale.price = item.price
            model_sale.member_id = item.member_id
            model_sale.created_time = getCurrentDate()
            model_sale.save()

        # 将任务加入数据库对列
        QueueService.addQueue('pay', {
            'member_id': pay_order_info.member_id,
            'pay_order_id': pay_order_info.id
        })
        return True

    def orderClose(self, pay_order_id):
        res = {'code': 200, 'msg': '操作成功！', 'data': {}}
        # 修改订单状态
        pay_order = PayOrder.query.filter_by(id=pay_order_id).first()
        if not pay_order:
            res['code'] = -1
            res['msg'] = "系统繁忙。请稍后再试~~"
            return res
        # 订单显示关闭
        pay_order.status = 0
        pay_order.updated_time = getCurrentDate()
        pay_order.update()
        # 归还库存
        pay_order_item_list = PayOrderItem.query.filter_by(pay_order_id=pay_order_id).all()
        if not pay_order_item_list:
            res['code'] = -1
            res['msg'] = "系统繁忙。请稍后再试~~"
            return res
        for item in pay_order_item_list:
            food = Food.query.filter(Food.id == item.food_id).first()
            food.stock = food.stock + item.quantity
            food.updated_time = getCurrentDate()
            food.update()
            # 添加库存变更记录
            ChangeFoodStockLog(item.food_id, item.quantity, '订单取消')
            # 修改订单详情记录
            item.status = 0
            item.updated_time = getCurrentDate()
            item.update()
        return res

    def addPayCallbackData(self, pay_order_id=0, type='pay', data=''):
        model_callback = PayOrderCallbackData()
        model_callback.pay_order_id = pay_order_id
        if type == "pay":  # 支付
            model_callback.pay_data = data
            model_callback.refund_data = ''
        else:  # 退款
            model_callback.refund_data = data
            model_callback.pay_data = ''

        model_callback.created_time = getCurrentDate()
        model_callback.updated_time = getCurrentDate()
        model_callback.save()

        return True
